﻿#pragma once
#include "yzrutil.h"
#include "RingBuffer.h"
#include "InterpolateFunction.h"
namespace yzrilyzr_dsp{
	EBCLASS(BufferDelayer){
	public:
	typedef u_sample(*DelayFunction)(RingBufferSample & buffer, u_sample index);
	static inline u_sample lagrangeDelay(RingBufferSample & buffer, u_sample index){
		u_index n=4;
		u_sample res=0;
		u_index start=(u_index)index - n / 2;
		u_index end=start + n;
		for(u_index i=start;i < end;i++){
			u_sample term=buffer.getFromNewest(i);
			for(u_index j=start;j < end;j++){
				if(i != j){
					term*=(index - j) / (i - j);
				}
			}
			res+=term;
		}
		return res;
	}
	static inline u_sample cubicSplineDelay(RingBufferSample & buffer, u_sample index){
		u_index lim=buffer.capacity();
		u_index indexI=static_cast<u_index>(index);
		u_sample * buf=buffer.buffer;
		u_index pt=buffer.pointer() - 1 - indexI;
		u_sample y0=buf[RingBufferUtil::mod(pt + 1, lim)];
		u_sample y1=buf[RingBufferUtil::mod(pt, lim)];
		u_sample y2=buf[RingBufferUtil::mod(pt - 1, lim)];
		u_sample y3=buf[RingBufferUtil::mod(pt - 2, lim)];
		u_sample out=InterpolateFunction::cubicSpline(index, indexI, y0, y1, y2, y3);
		return out;
	}
	static inline u_sample linearDelay(RingBufferSample & buffer, u_sample index){
		u_index indexI=static_cast<u_index>(index);
		u_sample * buf=buffer.buffer;
		u_index lim=buffer.capacity();
		u_index pt=buffer.pointer() - 1 - indexI;
		u_sample y0=buf[RingBufferUtil::mod(pt, lim)];
		u_sample y1=buf[RingBufferUtil::mod(pt - 1, lim)];
		return InterpolateFunction::linear(index, indexI, y0, y1);
	}
	static inline u_sample PCHIPDelay(RingBufferSample * buffer, u_sample index){
		u_index integerPart=static_cast<u_index>(index);
		u_sample frac=index - integerPart;

		// 获取相邻4个点：y0, y1, y2, y3
		u_sample y0=buffer->getFromNewest(integerPart + 2);
		u_sample y1=buffer->getFromNewest(integerPart + 1);
		u_sample y2=buffer->getFromNewest(integerPart);
		u_sample y3=buffer->getFromNewest(integerPart - 1);

		// 计算斜率
		u_sample m1=InterpolateFunction::PCHIPSlope(y0, y1, y2, y3);
		u_sample m2=InterpolateFunction::PCHIPSlope(y1, y2, y3, y3); // 简化处理

		// 插值
		return InterpolateFunction::PCHIP(frac, 0.0f, 1.0f, y2, y3, m1, m2);
	}
	// 在 RingBuffer 中调用 Akima
	static inline u_sample readAkima(RingBufferSample * buffer, u_sample index){
		u_index integerPart=static_cast<u_index>(index);
		u_sample frac=index - integerPart;

		// 获取相邻5个点：y_prev2, y_prev1, y0, y1, y2
		u_sample y_prev2=buffer->getFromNewest(integerPart + 3);
		u_sample y_prev1=buffer->getFromNewest(integerPart + 2);
		u_sample y0=buffer->getFromNewest(integerPart + 1);
		u_sample y1=buffer->getFromNewest(integerPart);
		u_sample y2=buffer->getFromNewest(integerPart - 1);

		// 计算斜率
		u_sample m=InterpolateFunction::akimaSlope(y_prev2, y_prev1, y0, y1, y2);
		u_sample m0=InterpolateFunction::akimaSlope(y_prev1, y0, y1, y2, y2); // 简化处理
		u_sample m1=m;

		// 插值
		return InterpolateFunction::akima(frac, 0.0f, 1.0f, y1, y2, m0, m1);
	}
	};
}